package com.senthink.gl.business.auth;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.senthink.gl.business.common.entity.PageDto;
import com.senthink.gl.business.common.entity.SearchRequest;
import com.senthink.gl.business.common.exception.BusinessException;
import com.senthink.gl.business.common.exception.DataAccessException;
import com.senthink.gl.business.domain.entity.Area;
import com.senthink.gl.business.domain.entity.User;
import com.senthink.gl.business.domain.service.AreaDataService;
import com.senthink.gl.business.domain.service.UserService;
import com.senthink.gl.business.messages.CodeMsg;
import com.senthink.gl.business.response.ApiResponse;
import com.senthink.gl.business.response.CodeMsgDataResponse;
import com.senthink.gl.business.security.JwtTokenUtils;
import com.senthink.gl.business.userlog.SystemUserLog;
import com.senthink.gl.business.userlog.enums.LogDetailEnum;
import com.senthink.gl.business.userlog.enums.LogOperateEnum;
import com.senthink.gl.business.userlog.enums.LogTypeEnum;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Optional;


/**
 * Created by lenovo on 2017/11/23.
 */
@Service
public class AccountService {

    @Autowired
    private CodeMsg codeMsg;
    @Autowired
    private AuthService authService;
    @Autowired
    private UserService userService;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private JwtTokenUtils jwtTokenUtils;
    @Autowired
    private AreaDataService areaDataService;


    @Value("${jwt.prefix}")
    private String prefix;

    private Logger LOGGER = LoggerFactory.getLogger(AccountService.class);

    /**
     * 修改用户信息
     *
     * @param userDTO
     * @return
     */
    @SystemUserLog(operate = LogOperateEnum.UPDATE, detail = LogDetailEnum.UPDATE_USER, logType = LogTypeEnum.USER)
    public ApiResponse updateUserRequest(UpdateUserRequest userDTO, String authorization) {
        String token = authorization.substring(prefix.length());
        User user = userService.findByUid(userDTO.getUid())
                .orElseThrow(() -> new BusinessException(codeMsg.accountNotExistCode(), codeMsg.accountNotExistMsg()));

        //校验用户手机、账户合法性
        if (!userDTO.getMobile().equalsIgnoreCase(user.getMobile())) {
            if (userService.findByMobile(userDTO.getMobile()).isPresent()) {
                return new CodeMsgDataResponse(codeMsg.userExistCode(), codeMsg.userExistMsg());
            }
        }
        User newUser = new User();
        BeanUtils.copyProperties(user, newUser);
        BeanUtils.copyProperties(userDTO, newUser,"uid", "enable");

        if (!userDTO.getAccount().equalsIgnoreCase(user.getAccount())) {
            if (userService.findByAccount(userDTO.getAccount()).isPresent()) {
                return new CodeMsgDataResponse(codeMsg.userExistCode(), codeMsg.userExistMsg());
            }

        }
        //验证是否修改密码
        if (StringUtils.isNotBlank(userDTO.getPassword())) {
            newUser.setPassword(passwordEncoder.encode(userDTO.getPassword()));
            newUser.setLastPwdRestDate(new Date());
        } else {
            newUser.setPassword(user.getPassword());
        }

        newUser = userService.saveUser(newUser);

        // 更新区域信息
        if(userDTO.getAid()!=null) {
            Optional<Area> area = areaDataService.findByAid(userDTO.getAid());
            if(area.isPresent()) {
                user.setArea(area.get());
            }
        }
        return new CodeMsgDataResponse<>(codeMsg.successCode(), codeMsg.successMsg(), toResponse(newUser));
    }

    /**
     * 用户列表
     *
     * @param role
     * @param searchRequest
     * @param pageable
     * @return
     */
    public ApiResponse userList(String aid, Boolean enable, String role, SearchRequest searchRequest, PageDto pageable) {
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        PageRequest page = pageable.convertToPageRequest(sort);
        Page<User> list = userService.findAll(aid, enable, role, page, searchRequest);
        return new CodeMsgDataResponse<>(codeMsg.successCode(), codeMsg.successMsg(), list);
    }

    /**
     * 获取用户详情
     *
     * @param uid
     * @return
     */
    public ApiResponse getDetailByUid(String uid) {
        User user = userService.findByUid(uid)
                .orElseThrow(() -> new BusinessException(codeMsg.accountNotExistCode(), codeMsg.accountNotExistMsg()));
        return new CodeMsgDataResponse<>(codeMsg.successCode(), codeMsg.successMsg(), toResponse(user));
    }

    /**
     * 获取用户详情
     *
     * @param account
     * @return
     */
    public ApiResponse getDetailByAccount(String account) {
        User user = userService.findByAccount(account)
                .orElseThrow(() -> new BusinessException(codeMsg.accountNotExistCode(), codeMsg.accountNotExistMsg()));
        return new CodeMsgDataResponse<>(codeMsg.successCode(), codeMsg.successMsg(), toResponse(user));
    }

    /**
     * 禁用或启用用户
     *
     * @param uid
     * @param enable
     * @return
     */
    @Transactional(rollbackFor = DataAccessException.class)
    @SystemUserLog(operate = LogOperateEnum.UPDATE, detail = LogDetailEnum.ENABLE_USER, logType = LogTypeEnum.USER)
    public ApiResponse enabled(String uid, boolean enable) {
        User user = userService.findByUid(uid).orElseThrow(() -> new BusinessException(codeMsg.accountNotExistCode(), codeMsg.accountNotExistMsg()));
        user.setEnable(!enable);
        userService.saveUser(user);
        return new CodeMsgDataResponse<>(codeMsg.successCode(), codeMsg.successMsg());
    }

    /**
     * 删除用户
     *
     * @param request
     * @return
     */
    @SystemUserLog(operate = LogOperateEnum.DELETE, detail = LogDetailEnum.DELETE_USER, logType = LogTypeEnum.USER)
    @Transactional
    public ApiResponse delete(UpdateUserRequest request) {
        authService.deleteAuthorities(request.getUid());
        if (userService.delete(request.getUid()) >= 1) {
            return new CodeMsgDataResponse<>(codeMsg.successCode(), codeMsg.successMsg());
        }
        throw new BusinessException(codeMsg.accountNotExistCode(), codeMsg.accountNotExistMsg());
    }

    /**
     * 将User对象转换为UserDetailResponse对象(把密码相关的信息过滤掉)
     *
     * @param user
     * @return
     */
    private UserResponse toResponse(User user) {
        UserResponse response = new UserResponse();
        BeanUtils.copyProperties(user, response);
            return response;
    }
}
